package com.htfyun.roobofactory.factorytest;

import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v4.widget.SwipeRefreshLayout;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import com.htfyun.roobofactory.BaseActivity;
import com.htfyun.roobofactory.R;
import com.htfyun.roobofactory.config.AppConfig;
import com.htfyun.roobofactory.config.RooboBuildConfig;
import com.htfyun.roobofactory.utils.PermissionManager;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by sst on 2018/7/9.
 */

public class BluetoothTestActivity extends BaseActivity {

    private Button btnPass;
    private Button btnFail;

    private TextView txtBTStatus;
    private TextView txtBTDiscoveryStatus;
    private TextView txtAutoTestSSID;

    private ListView listView;
    private DeviceAdapter deviceAdapter;

    private SwipeRefreshLayout mSwipeLayout;


    private BluetoothAdapter bluetoothAdapter;

    private Handler mHandler = new Handler();

    private Map<String, BTDeviceWithRSSI> bluetoothDeviceMap = new HashMap<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_factorytest_bt);
        mSwipeLayout = (SwipeRefreshLayout) findViewById(R.id.swipeRefreshLayout);

        mSwipeLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                bluetoothDeviceMap.clear();
                updateDeviceList();

            }
        });

        btnPass = (Button) findViewById(R.id.btnPass);
        btnFail = (Button) findViewById(R.id.btnFail);
        btnPass.setOnClickListener(onPassOrFailClickListener);
        btnFail.setOnClickListener(onPassOrFailClickListener);

        btnPass.setVisibility(RooboBuildConfig.FT_ADD_PASS_BTN ? View.VISIBLE : View.GONE);

        txtBTStatus = (TextView) findViewById(R.id.txtBTStatus);
        txtBTDiscoveryStatus = (TextView) findViewById(R.id.txtBTDiscoveryStatus);
        txtAutoTestSSID = (TextView) findViewById(R.id.txtAutoTestSSID);
        txtAutoTestSSID.setText(getString(R.string.test_scan_bt_ssid, AppConfig.BT_NAME_PASSED));
        txtBTDiscoveryStatus.setText("");
        txtBTStatus.setText("");

        listView = (ListView) findViewById(R.id.listView);
        deviceAdapter = new DeviceAdapter(this, -1);
        listView.setAdapter(deviceAdapter);

        bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        if (bluetoothAdapter == null) {

            Toast.makeText(this, R.string.test_bt_unsupported, Toast.LENGTH_LONG).show();
            ActivityCompat.finishAfterTransition(BluetoothTestActivity.this);

        }

    }

    @Override
    protected void onResume() {
        super.onResume();

        bluetoothDeviceMap.clear();

        registerReceiver(BTReceiver, getIntentFilterOfBT());

        initPermission();

    }

    @Override
    protected void onPause() {
        super.onPause();

        unregisterReceiver(BTReceiver);

        if (bluetoothAdapter.isEnabled()) {
            bluetoothAdapter.cancelDiscovery();
        }
    }

    private void setBtnPassOrFailEnabled(boolean enabled) {
        btnFail.setEnabled(enabled);
        btnPass.setEnabled(enabled);
    }

    private View.OnClickListener onPassOrFailClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (v == btnPass) {

                setResult(RESULT_OK);
                ActivityCompat.finishAfterTransition(getActivity());

            } else if (v == btnFail) {

                setResult(RESULT_CANCELED);
                ActivityCompat.finishAfterTransition(getActivity());

            }
        }
    };


    private void initPermission() {

        if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
                || ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {

            //同时申请多个权限
            PermissionManager.getInstance(getApplicationContext()).execute(this,
                    Manifest.permission.ACCESS_FINE_LOCATION,
                    Manifest.permission.ACCESS_COARSE_LOCATION);


        } else {

            startDiscovery();

        }


    }

    @Override
    public void onRequestPermissionsResult(int requestCode,  @NonNull String[] permissions,  @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        PermissionManager.getInstance(getApplicationContext()).
                onRequestPermissionsResult(requestCode, permissions, grantResults);

        Log.e(TAG, "bluetooth ~~~~~~~~~~~~~~onRequestPermissionsResult");

        startDiscovery();


    }

    private void startDiscovery() {

        int statusResId = R.string.bt_status_on;

        if (bluetoothAdapter.isEnabled()) {
            bluetoothAdapter.startDiscovery();
        } else {
            bluetoothAdapter.enable();
            statusResId = R.string.bt_status_off;
        }

        txtBTStatus.setText(getString(R.string.test_bt_status, getString(statusResId)));

    }

    private synchronized void updateDeviceList() {
        deviceAdapter.setNotifyOnChange(false);
        deviceAdapter.clear();

        Collection<BTDeviceWithRSSI> all = bluetoothDeviceMap.values();
        List<BTDeviceWithRSSI> list = new ArrayList<>(all);
        Collections.sort(list);

        deviceAdapter.setNotifyOnChange(true);
        deviceAdapter.addAll(list);

    }

    private IntentFilter getIntentFilterOfBT() {
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
        intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
        intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
        intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
        return intentFilter;
    }

    private BroadcastReceiver BTReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
            if (action == null) {
                return;
            }

            if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {

                String stateExtra = BluetoothAdapter.EXTRA_STATE;
                int state = intent.getIntExtra(stateExtra, -1);
                int statusResId = R.string.bt_status_unknown;

                switch(state) {
                    case BluetoothAdapter.STATE_TURNING_ON:
                        statusResId = R.string.bt_status_turning_on;
                        break;
                    case BluetoothAdapter.STATE_ON:
                        statusResId = R.string.bt_status_on;
                        bluetoothAdapter.startDiscovery();
                        break;
                    case BluetoothAdapter.STATE_TURNING_OFF:
                        statusResId = R.string.bt_status_turning_off;
                        bluetoothAdapter.cancelDiscovery();
                        break;
                    case BluetoothAdapter.STATE_OFF:
                        statusResId = R.string.bt_status_off;
                        break;
                }

                txtBTStatus.setText(getString(R.string.test_bt_status, getString(statusResId)));

            } else if (action.equals(BluetoothAdapter.ACTION_DISCOVERY_STARTED)) {
                txtBTDiscoveryStatus.setText(getString(R.string.test_bt_discovery_status, getString(R.string.bt_discovery_status_doing)));
            } else if (action.equals(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)) {
                txtBTDiscoveryStatus.setText(getString(R.string.test_bt_discovery_status, getString(R.string.bt_discovery_status_done)));
                mHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        if (bluetoothAdapter.isEnabled()) {
                            bluetoothAdapter.startDiscovery();
                        }
                    }
                }, 2 * 1000);
            } else if (action.equals(BluetoothDevice.ACTION_FOUND)) {

                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);


                if (device != null) {

                    Log.e(TAG, "found device = " + device.getAddress());

                    short rssi = -1;
                    if (intent.getExtras() != null) {
                        rssi = intent.getExtras().getShort(BluetoothDevice.EXTRA_RSSI);
                    }
                    BTDeviceWithRSSI btDeviceWithRSSI = bluetoothDeviceMap.get(device.getAddress());
                    if (btDeviceWithRSSI == null) {
                        btDeviceWithRSSI = new BTDeviceWithRSSI(device, rssi);
                        bluetoothDeviceMap.put(device.getAddress(), btDeviceWithRSSI);
                    }
                    btDeviceWithRSSI.rssi = rssi;
                    String name = device.getName();
                    if (!TextUtils.isEmpty(name) && name.equals(AppConfig.BT_NAME_PASSED)
                            && rssi > AppConfig.BT_RSSI_MIN ) {

                        startAutoPass(R.string.test_bt_pass);

                    }

                    updateDeviceList();

                    mSwipeLayout.setRefreshing(false);

                }

            }
        }
    };

    private class DeviceAdapter extends ArrayAdapter<BTDeviceWithRSSI> {

        public DeviceAdapter(@NonNull Context context, int resource) {
            super(context, resource);
        }

        @NonNull
        @Override
        public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
            ViewHolder holder = null;
            if (convertView != null) {
                holder = (ViewHolder) convertView.getTag();
            }
            if (holder == null) {
                holder = new ViewHolder();
                LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                convertView = inflater.inflate(R.layout.item_bt_devices, null);
                holder.txtName = (TextView) convertView.findViewById(R.id.txtName);
                holder.txtRSSI = (TextView) convertView.findViewById(R.id.txtRSSI);

                convertView.setTag(holder);
            }

            BTDeviceWithRSSI btDeviceWithRSSI = getItem(position);

            if (btDeviceWithRSSI != null) {

                String name = btDeviceWithRSSI.device.getName();
                if (TextUtils.isEmpty(name)) {
                    name = btDeviceWithRSSI.device.getAddress();
                }
                holder.txtName.setText(name);
                holder.txtRSSI.setText(Short.toString(btDeviceWithRSSI.rssi));

            }

            return convertView;
        }
    }

    private final class ViewHolder {

        private TextView txtName;
        private TextView txtRSSI;
    }

    private final class BTDeviceWithRSSI implements Comparable<BTDeviceWithRSSI> {
        BluetoothDevice device;
        short rssi;

        public BTDeviceWithRSSI(BluetoothDevice device, short rssi) {
            this.device = device;
            this.rssi = rssi;
        }


        @Override
        public int compareTo(@NonNull BTDeviceWithRSSI o) {
            return this.rssi - o.rssi;
        }
    }

}
